﻿using CacheHelper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XKPlatform.Common;
using XKPlatform.Common.Const;
using XKPlatform.Common.Enums;
using XKPlatform.DataModels.Model;

namespace XKPlatform.Filter
{
    public class CustomAuthorizationFilter : IAuthorizationFilter
    {

        private static ICache _cache = HttpContextCore.ServiceProvider.GetService(typeof(ICache)) as ICache;

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            //if (context.Filters.Any(item => item is IAllowAnonymousFilter))
            //{
            //    return;
            //}

            //if (!(context.ActionDescriptor is ControllerActionDescriptor))
            //{
            //    return;
            //}

            var user = context.HttpContext.User;
            var request = context.HttpContext.Request;
            //Console.WriteLine("path:" + request.Path);
            var token = request.Headers["Authorization"];//获取token
            string path = request.Path.Value;
            string ip = context.HttpContext.Connection.RemoteIpAddress.ToString();
            Console.WriteLine("=====log=======" + DateTime.Now.ToLocalTime() + "|path=" + path + "|token=" + token + "|ip=" + ip);


            if (!path.Contains(".") && path != "/" && !path.Contains("Account/Login") && !path.Contains("qrtzmanager"))
            {
                Console.WriteLine("===========" + path);
                List<Permisson> list = getPermissionList();
                //1、判断是否有token
                if (string.IsNullOrWhiteSpace(token))
                {
                    //判断接口是否需要权限
                    var item = list.Where(o => o.UrlAddr.Contains(path) && o.IsNeedPermisson == false).FirstOrDefault();
                    if (item == null)
                    {
                        CheckTokenIsRight(context.HttpContext, false);
                        return;
                    }

                }

                string[] arrToken = token.ToString().Split(' ', options: StringSplitOptions.RemoveEmptyEntries);

                if (arrToken.Length < 2)
                {
                    CheckTokenIsRight(context.HttpContext, false);
                    return;
                }
                //2、验证token 是否合法 如果无效 则返回
                (bool, AccessTokenDataModel) items = SSOClient.CheckToken(arrToken[1]);

                CheckTokenIsRight(context.HttpContext, items.Item1);
                if (!items.Item1)
                {
                    return;
                }
                //3、验证用户是否有api访问权限 
                // 获取用户信息 
                string userJsn = items.Item2.UserInfo;
                JObject jo = (JObject)JsonConvert.DeserializeObject(userJsn);
                var userRole = jo["DefaultRoleID"] ?? "";
                var userNo = jo["UserNo"] ?? "";
                //如果是管理员，则不用判断权限
                if (userRole.ToString().ToUpper() != "1")//== "EBF7BF27-3892-4F6D-899E-A484FAAAF2B4"|| userRole.ToString().ToUpper() == "37FDB939-3F22-4BA2-B89C-15E368EEAA2C"
                {
                    context.HttpContext.Request.Headers.Add("userInfo", Convert.ToBase64String(Encoding.UTF8.GetBytes(userJsn)));

                    // 刷新token
                    SSOClient.RefreshToken(items.Item2.LoginType, arrToken[1], context.HttpContext);
                    //记录操作日志
                    //OperateLog(context.HttpContext);
                    //await _next(context);
                }
                else
                {

                    // List<Permisson> list = getPermissionList();
                    var perList1 = list.Where(c => c.UrlAddr.Contains(path) || path.Contains(c.UrlAddr));
                    if (perList1 != null)
                    {
                        var perList = perList1.ToList();
                        if (perList.Count == 0)
                        {
                            ReturnContent(context.HttpContext, HttpStatusEnum.没有权限访问此接口);
                            return;
                        }
                        if (perList != null && perList.Count > 0 && perList[0].IsNeedPermisson)
                        {
                            var isExsit = perList.Where(o => (o.RoleId == null ? "" : o.RoleId.ToUpper()) == userRole.ToString().ToUpper());
                            if (isExsit == null || isExsit.FirstOrDefault() == null)
                            {
                                ReturnContent(context.HttpContext, HttpStatusEnum.没有权限访问此接口);
                                return;
                            }
                            context.HttpContext.Request.Headers.Add("userInfo", Convert.ToBase64String(Encoding.UTF8.GetBytes(userJsn)));
                            // 刷新token
                            SSOClient.RefreshToken(items.Item2.LoginType, arrToken[1], context.HttpContext);

                        }
                    }
                    else
                    {
                        ReturnContent(context.HttpContext, HttpStatusEnum.没有权限访问此接口);
                        return;
                    }
                }
            }


        }

        /// <summary>
        /// 调用接口不合法返回用户信息
        /// </summary>
        /// <param name="context"></param>
        /// <param name="httpStatus"></param>
        /// <returns></returns>
        private void ReturnContent(HttpContext context, HttpStatusEnum httpStatus)
        {
            context.Response.StatusCode = (int)httpStatus; //(int)httpStatusEnum.;
            context.Response.WriteJsonAsync(JsonConvert.SerializeObject(new { code = (int)httpStatus, msg = httpStatus.ToString() }));
            return;
        }
        /// <summary>
        /// 记录操作日志 记录每个接口被用户调用情况 TODO
        /// </summary>
        /// <param name="apiUrl"></param>
        /// <param name="userNo"></param>
        private void OperateLog(HttpContext context)
        {
            if (GlobleConst.IsWriteOperationLog) // 是否写操作日志
            {
                LogHelper.SaveOperaLog(context, SysOperationLogTypeEnum.InterfaceCall);
            }

        }
        /// <summary>
        /// 验证token是否合法有效 非法则跳转到登陆页
        /// </summary>
        /// <param name="context"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        private void CheckTokenIsRight(HttpContext context, bool tokenIsRight)
        {

            // 如果是认证中心登录失败的话则跳转到认证中心登录也
            string skipUrl = "";
            if (!tokenIsRight)
            {
                context.Response.StatusCode = (int)HttpStatusEnum.token过期;

                // LogHelper.SaveOperateLog("path:" + context.Request.Path + "token:" + context.Request.Headers["Authorization"] + "-time:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "token无效跳转");

                Console.WriteLine("token过期===" + context.Request.Path); 
                skipUrl = SSOClient.MidEdnLoginUrl; 
                context.Response.WriteJsonAsync(JsonConvert.SerializeObject(new { code = (int)HttpStatusEnum.token过期, msg = skipUrl }));  //context.Response.WriteAsync(skipUrl);

                return;
            }


        }
        // throw new NotImplementedException();

        /// <summary>
        /// 获取所有api 和角色的对应关系
        /// </summary>        /// <returns></returns>
        public List<Permisson> getPermissionList()
        {
            List<Permisson> list;
            //缓存取，没有则取数据库
            try
            {
                if (_cache.KeyExists(RedisKeyConst.PermissionList))
                {
                    list = JsonConvert.DeserializeObject<List<Permisson>>(_cache.GetOrDefault(RedisKeyConst.PermissionList));
                    return list;
                }

                list = ModelHelper<Permisson>.ConvertToModelList(SqlHelper.Query(@"select  a.UrlAddr,a.ApiName, a.IsNeedPermisson,b.RoleId from  sysApi a
left join  RoleAPIMapping b on a.ID = b.ApiId").Tables[0]);

                _cache.Set(RedisKeyConst.PermissionList, JsonConvert.SerializeObject(list));

                return list;
            }
            catch
            {
                list = ModelHelper<Permisson>.ConvertToModelList(SqlHelper.Query(@"select  a.UrlAddr,a.ApiName, a.IsNeedPermisson,b.RoleId from  sysApi a
left join  RoleAPIMapping b on a.ID = b.ApiId").Tables[0]);

                return list;
            }
            //   SysUser user = ModelHelper<Permisson>.ConvertToModel(SqlHelper.Query(querySuite.SelectSql, querySuite.Params).Tables[0]);
        }
    }
}

